package net.openl10n.packaging;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import net.openl10n.opc4j.PackagePart;


public abstract class AbstractJaxbContentPart extends OpenLocPart implements IFixedContentTypePart{
	
	protected AbstractJaxbContentPart(OpenLocPartContainer container, PackagePart part, OpenLocPartFactoryManager partFactoryManager) {
		super(container, part, partFactoryManager);
	}
	
	protected <T> T tryLoadJaxbObject(Class<T> clz){
		T instance;
		try{
			JAXBContext context = JAXBContext.newInstance(clz);
			Unmarshaller um = context.createUnmarshaller();
			InputStream in = getInputStream();
			instance = clz.cast(um.unmarshal(in));
			in.close();
			return instance;
		}
		catch(JAXBException e){
			// expected when the object doesn't yet exist
			return null;
		}
		catch(IOException e){
			throw new RuntimeException(e);
		}
	}
	
	protected <T> T loadOrCreateJaxbObject(Class<T> clz){
		T instance = tryLoadJaxbObject(clz);
		if(instance == null){
			try {
				instance = clz.newInstance();
			} catch (InstantiationException e) {
				throw new RuntimeException(e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException(e);
			}
		}
		return instance;
	}

	protected <T> void saveJaxbObject(T object){
		try{
			JAXBContext context = JAXBContext.newInstance(object.getClass());
			Marshaller m = context.createMarshaller();
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			OutputStream out = getOutputStream();
			m.marshal(object, out);
			out.close();
		}
		catch(JAXBException e){
			throw new RuntimeException(e);
		}
		catch(IOException e){
			throw new RuntimeException(e);
		}
	}

}
